package org.six11.olive3.picturephone;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import org.six11.olive3.client.OliveDrawingSurface;
import org.six11.olive3.client.OliveState;
import org.six11.olive3.net.Message;
import org.six11.olive3.net.MessageHandler;
import org.six11.olive3.net.MessageNames;
import org.six11.olive3.net.OliveNetworkTransmitter;
import org.six11.olive3.picturephone.server.PPMessageNames;
import org.six11.olive3.util.MiscFunctions;
import org.six11.olive3.util.MultiState;
import org.six11.util2.Debug;
import org.six11.util2.layout.FrontEnd;
import org.six11.util2.lev.NamedAction;

import static org.six11.util2.layout.FrontEnd.*;

/**
 * 
 * 
 * @author Gabe Johnson <johnsogg@cmu.edu>
 * 
 */
public class PicturephoneDescriptionPane extends JPanel {

  private static String DRAW = "draw";
  private static String DESC_LABEL = "description label";
  private static String DESC = "description text";
  private static String CONTROLS = "control box";

  private OliveState oliveState;
  private JTextArea text;
  private MultiState programState;
  private PicturephoneControlBox controlBox;
  private List<NamedAction> actions;

  public PicturephoneDescriptionPane(final OliveNetworkTransmitter xmit,
      final MultiState programState) {
    this.programState = programState;
    this.actions = new ArrayList<NamedAction>();
    NamedAction doneAction = new NamedAction("Done") {
      public void activate() {
        String sketchID = programState.getString(PPMessageNames.PARAM_SKETCH_ID);
        if (sketchID != null) {
          String descText = MiscFunctions.escape(text.getText());
          Message m = new Message(PPMessageNames.MSG_DESC_DONE);
          (m).addParam(MessageNames.PARAM_USER_ID, programState
              .getString(MessageNames.PARAM_USER_ID));
          m.addParam(PPMessageNames.PARAM_SKETCH_ID, sketchID);
          m.addParam(PPMessageNames.PARAM_DESC_TEXT, descText);
          xmit.addBodilessMessage(m);
          resetTemporaryState();
          bug("-> Described sketch " + sketchID);
        }
      }

      public synchronized void tweakState() {
        setEnabled(text.getDocument().getLength() > 0);
      }
    };
    actions.add(doneAction);

    NamedAction skipAction = new NamedAction("Skip") {
      public void activate() {
        String sketchID = programState.getString(PPMessageNames.PARAM_SKETCH_ID);
        resetTemporaryState();
        bug("-> Skipped sketch " + sketchID);
      }

      public synchronized void tweakState() {
        setEnabled(text.getDocument().getLength() == 0);
      }
    };
    actions.add(skipAction);

    controlBox = new PicturephoneControlBox(skipAction, doneAction, programState);

    FrontEnd fe = new FrontEnd();
    JLabel descLabel = new JLabel("Describe:");

    text = new JTextArea();
    text.setLineWrap(true);
    text.setWrapStyleWord(true);
    text.getDocument().addDocumentListener(new DocumentListener() {
      public void changedUpdate(DocumentEvent e) {
        tweakActions();
      }

      public void insertUpdate(DocumentEvent e) {
        tweakActions();
      }

      public void removeUpdate(DocumentEvent e) {
        tweakActions();
      }
    });
    JScrollPane textScroller = new JScrollPane(text,
        ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
        ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    oliveState = new OliveState(programState);
    OliveDrawingSurface draw = new OliveDrawingSurface(xmit, oliveState);
    xmit.getStreamHandler().registerAsynchronousHandler(MessageNames.MSG_PEN,
        draw.getForeignPenHandler());
    xmit.getStreamHandler().registerAsynchronousHandler(MessageNames.MSG_PEN, new MessageHandler() {
      public void handleLater(Message m) {
        programState.setValue(PPMessageNames.PARAM_SKETCH_ID, m
            .getParamValue(PPMessageNames.PARAM_SKETCH_ID));
        bug("* Describing based on sketch "
            + programState.getString(PPMessageNames.PARAM_SKETCH_ID));
      }
    });
    draw.setPenEnabled(false);
    draw.setPreferredSize(new Dimension(400, 400));
    draw.setMaximumSize(new Dimension(400, 400));
    fe.add(draw, DRAW);
    fe.add(descLabel, DESC_LABEL);
    fe.add(controlBox, CONTROLS);
    fe.add(textScroller, DESC);

    fe.addRule(ROOT, N, DRAW, N);
    fe.addRule(ROOT, W, DRAW, W);

    fe.addRule(ROOT, E, CONTROLS, E);
    fe.addRule(ROOT, N, CONTROLS, N);

    fe.addRule(CONTROLS, S, DESC_LABEL, N);
    fe.addRule(CONTROLS, W, DESC_LABEL, W, 12);

    fe.addRule(DESC_LABEL, S, DESC, N, 12);
    fe.addRule(ROOT, S, DESC, S);
    fe.addRule(ROOT, E, DESC, E);
    fe.addRule(DESC_LABEL, W, DESC, W);

    setLayout(new BorderLayout());
    add(fe, BorderLayout.CENTER);
     tweakActions();
  }

  protected void tweakActions() {
    for (NamedAction a : actions) {
      a.tweak();
    }
  }

  protected void bug(String what) {
    Debug.out("PicturephoneDescriptionPane", what);
  }

  protected void resetTemporaryState() {
    programState.setValue(PPMessageNames.PARAM_SKETCH_ID, null);
    text.setText("");
    oliveState.clearSurface();
    programState.whackValue(PicturephoneUI.DONE);
  }

}
